// todo: textchange事件应该需要参数使能知道是谁引起的，用户操作还是内部操作.

function TextModel(){
    this.init$TextModel();
}
(function (){

    // 注意什么内容都没有的时候, textModel认为有一个空行存在.

    TextModel.prototype = {
        init$TextModel: function (){
            this.init$LineTracker();
            this.init$Eventable();
            this.$chunkedText = new ChunkedText();
            this._linesData = [{}];
        },
        getLength: function (){
            return this.$chunkedText.getLength();
        },
        getText: function (startOffset, endOffset){
            if (startOffset == null || startOffset < 0) {
                startOffset = 0;
            }
            if (endOffset == null || endOffset > this.getLength()) {
                endOffset = this.getLength();
            }
            if (endOffset <= startOffset) {
                return '';
            }
            return this.$chunkedText.getText(startOffset, endOffset);
        },
        setText: function (text, startOffset, endOffset){
            if (startOffset == null || startOffset < 0) {
                startOffset = 0;
            }
            if (endOffset == null || endOffset > this.getLength()) {
                endOffset = this.getLength();
            }
            if (endOffset < startOffset) {
                endOffset = startOffset;
            }
            this._update(startOffset, endOffset, text);
            return startOffset + text.length;
        },
        setLineData: function (index, key, val){
            this._linesData[index][key] = val;
        },
        getLineData: function (index, key){
            return this._linesData[index][key];
        },
        _update: function (startOffset, endOffset, text){
            var deletedText = this.$chunkedText.getText(startOffset, endOffset);
            if (deletedText !== text) {
                this.$chunkedText.setText(text, startOffset, endOffset);
                var linechanges = this.update$LineTracker(startOffset, endOffset - startOffset, text);
                var array = [linechanges.startIndex, linechanges.endIndexOld-linechanges.startIndex];
                for (var i=0,l=linechanges.endIndex-linechanges.startIndex; i<l; i++) {
                    array.push({});
                }
                this.dispatchEvent({
                    type: 'Changing',
                    offset: startOffset,
                    deletedText: deletedText,
                    insertedText: text
                });
                this._linesData.splice.apply(this._linesData, array);
                this.dispatchEvent({
                    type: 'LinesChanged',
                    startIndex: linechanges.startIndex,
                    endIndexOld: linechanges.endIndexOld,
                    endIndex: linechanges.endIndex
                });
                this.dispatchEvent({
                    type: 'Changed',
                    offset: startOffset,
                    deletedText: deletedText,
                    insertedText: text
                });
            }
        }
    };

})();

Utils.extend(TextModel, LineTracker);
Utils.extend(TextModel, Eventable);
